package com.yjd.comm.fundservice.util;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.bank.dto.BankInfoDto;
import com.yjd.comm.bank.model.BankInfoModel;
import com.yjd.comm.bank.model.BankModel;
import com.yjd.comm.bank.service.IBankInfoService;
import com.yjd.comm.base.enums.DbWREnums;
import com.yjd.comm.enums.ReferenceTypeEnum;
import com.yjd.comm.enums.RepaymentWayEnum;
import com.yjd.comm.fundservice.dto.*;
import com.yjd.comm.fundservice.enums.BusTypeEnum;
import com.yjd.comm.order.model.OrderModel;
import com.yjd.comm.org.model.OrganizationModel;
import com.yjd.comm.user.dto.ContactInfo;
import com.yjd.comm.user.dto.ResidenceInfo;
import com.yjd.comm.user.dto.WorkInfo;
import com.yjd.comm.user.model.UserDataModel;
import com.yjd.comm.user.util.UserUtil;
import com.yjd.comm.util.*;
import org.springframework.util.Assert;

import java.util.*;

/**
 * 乾康接口对接服务
 * Created by yjd-wap on 2018/1/21.
 */
public class QianKangServer {

    /**
     * 借款申请
     * @param order_id 订单id
     * @param applyModel 订单贷款申请信息
     * @return
     * @throws Exception
     */
    public static QKLoanApplyResponse loanApply(Long order_id, QKLoanApplyModel applyModel) throws Exception {

        // 贷款申请的响应信息
        return QianKangServerUtil.sendMsg(applyModel, BusTypeEnum.LOAN_APPLY, order_id.toString(), QKLoanApplyResponse.class);
    }

    public static QKLoanApplyModel buildLoanApplyModel(
            OrganizationModel org, OrderModel order, UserDataModel userData, BankModel bank) throws Exception {

        QKLoanApplyModel request = new QKLoanApplyModel();
        request.setAgent_order_id(order.getOrder_no());
        request.setLoan_amount((int)ArithUtil.mul(order.getLoan_amount(),100));
        request.setLoan_rate(order.getLoan_rate());
        request.setLoad_period(order.getPeriod());
        request.setRepayment_way(RepaymentWayEnum.TYPE_3.getCode());
        request.setStart_date(""); // optional
        request.setEnd_date(""); // optional
        request.setProduct_name(""); // optional
        request.setProduct_desc(""); // optional
        request.setPayee_bank_account(org.getPayee_bank_account());
        request.setPayee_bank_card(org.getPayee_bank_card());
        request.setBorrower_name(bank.getId_name());
        request.setBorrower_id(bank.getId_number());
        request.setBorrower_contact(bank.getBank_mobile().toString());
        request.setBorrower_bank_code(2); //TODO
        request.setBorrower_bank_card(bank.getBank_card_number());

        // 借款人单位信息
        WorkInfo workInfo = JSON.parseObject(userData.getJob_info(), WorkInfo.class);
        if( !UserUtil.isJobInfoCompleted(workInfo) ){
            throw new IllegalArgumentException("借款人工作单位信息不完整");
        }
        request.setBorrower_work_name(workInfo.getCompany());
        request.setBorrower_work_address(workInfo.getCompanyLocation());

        // 借款人居住信息
        ResidenceInfo rdnInfo = JSON.parseObject(userData.getResidence(), ResidenceInfo.class);
        if( !UserUtil.isResidenceInfoCompleted(rdnInfo) ){
            throw new IllegalArgumentException("借款人居住信息不完整");
        }
        request.setBorrower_address(rdnInfo.getCurrentResidenceAddr().getFullAddress());
        request.setBorrower_home_address(rdnInfo.getFamilyAddr().getFullAddress());
        request.setBorrower_census_address(rdnInfo.getDomicileAddr().getFullAddress());

        // 借款人紧急联系人信息
        List<ContactInfo> contactInfos = JSON.parseArray(userData.getUrgent_contacts(), ContactInfo.class);
        if( !UserUtil.isUrgentContactInfoCompleted(contactInfos) ){
            throw new IllegalArgumentException("借款人紧急联系人信息不完整");
        }
        request.setBorrower_contact_first_name(contactInfos.get(0).getIdName());
        request.setBorrower_contact_first_phone(contactInfos.get(0).getMobile_number());
        request.setBorrower_contact_first_relation(contactInfos.get(0).getRelation());
        request.setBorrower_contact_second_name(contactInfos.get(1).getIdName());
        request.setBorrower_contact_second_phone(contactInfos.get(1).getMobile_number());
        request.setBorrower_contact_second_relation(contactInfos.get(1).getRelation());
        request.setCallback_url( QianKangServerUtil.getQKFundApplyCallbackUrl());

        return request;
    }

    /**
     * 查询还款计划
     * @param order_no 订单编号
     * @param period 还款期数（默认：0 则查询全部期数的计划列表）
     * @return
     * @throws Exception
     */
    public static QKRepaymentPlanModel queryRepaymentPlan(Long order_id, String order_no, int period) throws Exception {
        // 查询还款计划需要的信息
        QKRepaymentApplyModel request = new QKRepaymentApplyModel();
        request.setAgent_order_id(order_no);
//        if(period > 0){
//            request.setTerm_no(period);
//        }

        // 还款计划信息
        QKRepaymentPlanModel plan = QianKangServerUtil.sendMsg(request, BusTypeEnum.REPAYMENT_PLAN_QUERY, order_id.toString(), QKRepaymentPlanModel.class);
        Assert.notEmpty(plan.getRepayment_list(), "还款报表为空");

        // 还款报表排序
        Collections.sort(plan.getRepayment_list(), new Comparator<RepaymentPlanItem>() {
            @Override
            public int compare(RepaymentPlanItem p1, RepaymentPlanItem p2) {
                int p1RepaymentDate = Integer.valueOf(p1.getRepayment_date().replace("-", ""));
                int p2RepaymentDate = Integer.valueOf(p2.getRepayment_date().replace("-", ""));
                if(p1RepaymentDate > p2RepaymentDate){
                    return 1;
                }

                if(p1RepaymentDate < p2RepaymentDate){
                    return -1;
                }

                return 0;
            }
        });

        return plan;
    }

    /**
     * 还款申请接口
     * @param agent_order_id 我方订单号
     * @param order_id 对方订单号
     * @param term_no 还款期数
     * @param loan_amount 还款金额
     * @param idName 姓名
     * @param idcard 身份证
     * @return
     * @throws Exception
     */
    public static QkRepaymentAskResponse QKRepaymentAsk(String agent_order_id,String order_id,int term_no,Double loan_amount,Integer repayment_type,String idName,String idcard)throws Exception{
        QKRepaymentAskModel askModel = new QKRepaymentAskModel();
        askModel.setAgent_order_id(agent_order_id);
        askModel.setOrder_id(order_id);
        askModel.setRepayment_type(repayment_type);
        askModel.setTerm_no(term_no);
        askModel.setLoan_amount(loan_amount);
        askModel.setBorrower_name(idName);
        askModel.setBorrower_id_id(idcard);
        return  QianKangServerUtil.sendMsg(askModel, BusTypeEnum.LOAN_APPLY, askModel.getOrder_id(), QkRepaymentAskResponse.class);
    }

    /**
     * 四要素验证
     * @param user_id 用户id
     * @param id_name 真实姓名
     * @param id_number 身份证号码
     * @param bank_card_number 银行卡号
     * @param bank_mobile 银行预留手机号
     * @return
     * @throws Exception
     */
    public static QKFourElementsResponse fourElementsVerify(Long user_id, String id_name, String id_number, String bank_card_number, String bank_mobile) throws Exception {

        QKFourElementsRequest req = new QKFourElementsRequest();
        req.setName(id_name);
        req.setIdentity(id_number);
        req.setBank_card_no(bank_card_number);
        req.setPhone(bank_mobile);

        QKFourElementsResponse response = QianKangServerUtil.sendMsg(req, BusTypeEnum.FOUR_ELEMENTS, user_id.toString(), QKFourElementsResponse.class);
        Assert.notNull(response, "请稍后重试");
        BankCardInfo cardInfo = response.getBank_card_info();
        Assert.notNull(cardInfo, "银行卡信息不存在");

        /**
         * 四要素验证成功，返回银行信息（包括银行客服电话，此电话用于唯一标识一个银行，如工行95588。）
         * 根据银行客服电话查询本地银行信息，如果查询不到，说明不支持改银行卡。
         */
        List<BankInfoModel> localBankInfo = getLocalBankInfo(FrameUtil.newHashMap("bank_phone", cardInfo.getBank_phone()));
        BankInfoModel bim = matchBankInfoByPhone(cardInfo.getBank_phone(), localBankInfo);
        if(bim==null){
            FrameUtil.throwBaseException1("此银行卡暂不支持");
        }

        cardInfo.setBank_id(bim.getBank_id());
        cardInfo.setBank_name(bim.getBank_name());
        cardInfo.setBank_code(bim.getBank_code());

        // 全部status为1，表示通过
        if(response.getName_status() == 1 && response.getPhone_status() == 1 && response.getBank_card_no_status() == 1){
            return response;
        }

        // 以下为验证不通过的处理
        switch (response.getName_status()) {
            case 2:{FrameUtil.throwBaseException1("身份证与姓名不匹配");}
            case 3:{FrameUtil.throwBaseException1("身份证与姓名验证未通过");}
        }

        switch (response.getPhone_status()) {
            case 2:{FrameUtil.throwBaseException1("手机号码与持有人不匹配");}
            case 3:{FrameUtil.throwBaseException1("手机号码验证未通过");}
        }

        switch (response.getBank_card_no_status()) {
            case 2:{FrameUtil.throwBaseException1("银行卡与持有人不匹配");}
            case 3:{FrameUtil.throwBaseException1("银行卡验证未通过");}
            case 4:{FrameUtil.throwBaseException1("银行卡未校验");}
        }

        FrameUtil.throwBaseException1("四要素验证不通过，请核实信息后再次认证。");
        return  null;
    }

    /**
     * 查询支持的银行列表
     * @return
     * @throws Exception
     */
    public static List<BankInfoDto> querySupportBankList() throws Exception {
        QKSupportBankQueryRequest req = new QKSupportBankQueryRequest();
        List<BankItem> bankList = new ArrayList<>();

        // 第三方银行列表
        List list = QianKangServerUtil.sendMsg(req, BusTypeEnum.SUPPORT_BANK_LIST, "", List.class);
        for(Object obj:list){
            bankList.add(StringUtil.getObject(obj, BankItem.class));
        }

        // 转换银行信息
        List<BankInfoModel> localBankInfo = getLocalBankInfo(null);
        BankInfoDto info = null;
        BankInfoModel bim = null;
        List<BankInfoDto> bankInfoList = new ArrayList<>();
        for(BankItem itm : bankList){
            bim = matchBankInfoByPhone(itm.getBank_phone(), localBankInfo);
            if(null == bim){
                continue;
            }
            info = new BankInfoDto();
            info.setBank_id(bim.getBank_id());
            info.setBank_name(bim.getBank_name());
            info.setBank_code(bim.getBank_code());
            info.setBank_img(ServletUtil.getFileUrl(ReferenceTypeEnum.BANK_PICTURE.getPath() + info.getBank_code() + ".png"));
            bankInfoList.add(info);
        }

        return bankInfoList;
    }

    /**
     * 根据银行电话去匹配本地银行信息
     *
     * @param bankPhone 需要匹配的银行对应的电话
     * @param localBankInfo 本地银行列表
     * @return
     */
    private static BankInfoModel matchBankInfoByPhone(String bankPhone, List<BankInfoModel> localBankInfo){
        Iterator<BankInfoModel> itr = localBankInfo.iterator();

		/*
		循环匹配，如果匹配到了：1、返回银行银行信息，2、删除当前匹配到的元素
		 */
        BankInfoModel bim = null;
        while (itr.hasNext()){
            bim = itr.next();
            if(bim.getBank_phone() != null && bim.getBank_phone().contains(bankPhone)){
                itr.remove();
                return bim;
            }
        }

        return null;
    }

    private static List<BankInfoModel> getLocalBankInfo(Map param) throws Exception {
        if(null == param){
            param = FrameUtil.newHashMap();
        }
        param.put("is_available", 1);
        return ServiceHolder.getService(IBankInfoService.class, "bankInfoService").getModelList(param, DbWREnums.READ);
    }

}
